package analyticsServer;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

/**
 *
 * @author Group 95
 */
public class EventCalculator 
{
    private HashMap<Long,Auction> hmAuctions;
    private HashMap<String,Long> hmUsers;
    private long auction_time_full;
    private double auction_count;
    private int auction_count_successfull;
    private double session_count;
    private long session_time_full;
    private long session_time_min;
    private long session_time_max;
    private double bid_price_max;
    private int bid_count;
    private final long start_time;
    
    
    public EventCalculator()
    {
        this.hmAuctions=new HashMap<Long,Auction>();
        this.hmUsers=new HashMap<String,Long>();
        this.auction_time_full=0;
        this.auction_count=0;
        this.auction_count_successfull=0;
        this.session_count=0;
        this.session_time_full=0;
        this.session_time_min=Long.MAX_VALUE;
        this.session_time_max=0;
        this.bid_price_max=0;
        this.bid_count=0;
        this.start_time=System.currentTimeMillis();
    }
    
    
    public ArrayList<StatisticsEvent> calculate(AuctionEvent event)
    {
        ArrayList<StatisticsEvent> arRet=null;
        String type=event.getType();
        
        if(type.equals(AuctionEvent.AUCTION_STARTED))
        {
            this.hmAuctions.put(event.getAuctionId(),new Auction(event.timestamp));
        }
        else if(type.equals(AuctionEvent.AUCTION_ENDED))
        {
            arRet=new ArrayList<StatisticsEvent>(2);
            Auction auction=this.hmAuctions.remove(event.getAuctionId());
            if(auction.hasBid)
            {
                this.auction_count_successfull++;
            }
            this.auction_count++;
            this.auction_time_full+=event.getTimestamp()-auction.timestamp; //auction_time=ended-started
            arRet.add(new StatisticsEvent(AnalyticsServer.NAME,StatisticsEvent.AUCTION_TIME_AVG,
                    System.currentTimeMillis(),this.auction_time_full/this.auction_count));
            arRet.add(new StatisticsEvent(AnalyticsServer.NAME,StatisticsEvent.AUCTION_SUCCESS_RATIO,
                    System.currentTimeMillis(),this.auction_count_successfull/this.auction_count));
        }
        return arRet;
    }
    
    public synchronized ArrayList<StatisticsEvent> calculate(UserEvent event)
    {
        ArrayList<StatisticsEvent> arRet=null;
        String type=event.getType();
        
        if(type.equals(UserEvent.USER_LOGIN))
        {
            this.hmUsers.put(event.getUserName(),event.getTimestamp());
        }
        else if(type.equals(UserEvent.USER_LOGOUT)||type.equals(UserEvent.USER_DISCONNECTED))
        {
            arRet=new ArrayList<StatisticsEvent>(3);
            Long logintime=this.hmUsers.remove(event.getUserName());
            if(logintime!=null)
            {
                long session_time=event.getTimestamp()-logintime;
                if(session_time<this.session_time_min)
                {
                    this.session_time_min=session_time;
                    arRet.add(new StatisticsEvent(AnalyticsServer.NAME,StatisticsEvent.USER_SESSIONTIME_MIN,
                        System.currentTimeMillis(),this.session_time_min/1000));
                }
                if(session_time>this.session_time_max)
                {
                    this.session_time_max=session_time;
                    arRet.add(new StatisticsEvent(AnalyticsServer.NAME,StatisticsEvent.USER_SESSIONTIME_MAX,
                        System.currentTimeMillis(),this.session_time_max/1000));
                }                
                this.session_count++;
                this.session_time_full+=session_time;
                arRet.add(new StatisticsEvent(AnalyticsServer.NAME,StatisticsEvent.USER_SESSIONTIME_AVG,
                    System.currentTimeMillis(),this.session_time_full/this.session_count/1000));
            }
        }
        return arRet;
    }    
    
    
    public List<StatisticsEvent> calculate(final BidEvent event)
    {
        List<StatisticsEvent> arRet=null;
        final String type=event.getType();
        
        if(type.equals(BidEvent.BID_PLACED)||type.equals(BidEvent.BID_OVERBID))
        {
            arRet=new ArrayList<StatisticsEvent>(2);
            this.bid_count++;
            if(event.getPrice()>this.bid_price_max)
            {
                this.bid_price_max=event.getPrice();
                arRet.add(new StatisticsEvent(AnalyticsServer.NAME,StatisticsEvent.BID_PRICE_MAX,
                    System.currentTimeMillis(),event.getPrice()));
            }
            final double runtime_minutes=(System.currentTimeMillis()-this.start_time)/(double)60000;
            arRet.add(new StatisticsEvent(AnalyticsServer.NAME,StatisticsEvent.BID_COUNT_PER_MINUTE,
                System.currentTimeMillis(),this.bid_count/(double)runtime_minutes ));
        }
        return arRet;
    }  
    
    
    
    
    private static class Auction
    {
        private final long timestamp;
        private final boolean hasBid;
        
        private Auction(final long timestamp)
        {
            this.timestamp=timestamp;
            this.hasBid=false;
        }
    }
}
